home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / interp / perl-5.003.tar.gz / perl-5.003.tar / perl-5.003 / doop.c < prev    next >
C/C++ Source or Header  |  1996-01-26  |  13KB  |  685 lines

  1. /*    doop.c
  2.  *
  3.  *    Copyright (c) 1991-1994, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  */
  9.  
  10. /*
  11.  * "'So that was the job I felt I had to do when I started,' thought Sam."
  12.  */
  13.  
  14. #include "EXTERN.h"
  15. #include "perl.h"
  16.  
  17. #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  18. #include <signal.h>
  19. #endif
  20.  
  21. #ifdef BUGGY_MSC
  22.  #pragma function(memcmp)
  23. #endif /* BUGGY_MSC */
  24.  
  25. #ifdef BUGGY_MSC
  26.  #pragma intrinsic(memcmp)
  27. #endif /* BUGGY_MSC */
  28.  
  29. I32
  30. do_trans(sv,arg)
  31. SV *sv;
  32. OP *arg;
  33. {
  34.     register short *tbl;
  35.     register U8 *s;
  36.     register U8 *send;
  37.     register U8 *d;
  38.     register I32 ch;
  39.     register I32 matches = 0;
  40.     register I32 squash = op->op_private & OPpTRANS_SQUASH;
  41.     STRLEN len;
  42.  
  43.     if (SvREADONLY(sv))
  44.     croak(no_modify);
  45.     tbl = (short*)cPVOP->op_pv;
  46.     s = (U8*)SvPV(sv, len);
  47.     if (!len)
  48.     return 0;
  49.     if (!SvPOKp(sv))
  50.     s = (U8*)SvPV_force(sv, len);
  51.     (void)SvPOK_only(sv);
  52.     send = s + len;
  53.     if (!tbl || !s)
  54.     croak("panic: do_trans");
  55.     DEBUG_t( deb("2.TBL\n"));
  56.     if (!op->op_private) {
  57.     while (s < send) {
  58.         if ((ch = tbl[*s]) >= 0) {
  59.         matches++;
  60.         *s = ch;
  61.         }
  62.         s++;
  63.     }
  64.     }
  65.     else {
  66.     d = s;
  67.     while (s < send) {
  68.         if ((ch = tbl[*s]) >= 0) {
  69.         *d = ch;
  70.         if (matches++ && squash) {
  71.             if (d[-1] == *d)
  72.             matches--;
  73.             else
  74.             d++;
  75.         }
  76.         else
  77.             d++;
  78.         }
  79.         else if (ch == -1)        /* -1 is unmapped character */
  80.         *d++ = *s;        /* -2 is delete character */
  81.         s++;
  82.     }
  83.     matches += send - d;    /* account for disappeared chars */
  84.     *d = '\0';
  85.     SvCUR_set(sv, d - (U8*)SvPVX(sv));
  86.     }
  87.     SvSETMAGIC(sv);
  88.     return matches;
  89. }
  90.  
  91. void
  92. do_join(sv,del,mark,sp)
  93. register SV *sv;
  94. SV *del;
  95. register SV **mark;
  96. register SV **sp;
  97. {
  98.     SV **oldmark = mark;
  99.     register I32 items = sp - mark;
  100.     register STRLEN len;
  101.     STRLEN delimlen;
  102.     register char *delim = SvPV(del, delimlen);
  103.     STRLEN tmplen;
  104.  
  105.     mark++;
  106.     len = (items > 0 ? (delimlen * (items - 1) ) : 0);
  107.     if (SvTYPE(sv) < SVt_PV)
  108.     sv_upgrade(sv, SVt_PV);
  109.     if (SvLEN(sv) < len + items) {    /* current length is way too short */
  110.     while (items-- > 0) {
  111.         if (*mark) {
  112.         SvPV(*mark, tmplen);
  113.         len += tmplen;
  114.         }
  115.         mark++;
  116.     }
  117.     SvGROW(sv, len + 1);        /* so try to pre-extend */
  118.  
  119.     mark = oldmark;
  120.     items = sp - mark;;
  121.     ++mark;
  122.     }
  123.  
  124.     if (items-- > 0) {
  125.     char *s;
  126.  
  127.     if (*mark) {
  128.         s = SvPV(*mark, tmplen);
  129.         sv_setpvn(sv, s, tmplen);
  130.     }
  131.     else
  132.         sv_setpv(sv, "");
  133.     mark++;
  134.     }
  135.     else
  136.     sv_setpv(sv,"");
  137.     len = delimlen;
  138.     if (len) {
  139.     for (; items > 0; items--,mark++) {
  140.         sv_catpvn(sv,delim,len);
  141.         sv_catsv(sv,*mark);
  142.     }
  143.     }
  144.     else {
  145.     for (; items > 0; items--,mark++)
  146.         sv_catsv(sv,*mark);
  147.     }
  148.     SvSETMAGIC(sv);
  149. }
  150.  
  151. void
  152. do_sprintf(sv,len,sarg)
  153. register SV *sv;
  154. register I32 len;
  155. register SV **sarg;
  156. {
  157.     register char *s;
  158.     register char *t;
  159.     register char *f;
  160.     bool dolong;
  161. #ifdef HAS_QUAD
  162.     bool doquad;
  163. #endif /* HAS_QUAD */
  164.     char ch;
  165.     register char *send;
  166.     register SV *arg;
  167.     char *xs;
  168.     I32 xlen;
  169.     I32 pre;
  170.     I32 post;
  171.     double value;
  172.     STRLEN arglen;
  173.  
  174.     sv_setpv(sv,"");
  175.     len--;            /* don't count pattern string */
  176.     t = s = SvPV(*sarg, arglen);    /* XXX Don't know t is writeable */
  177.     send = s + arglen;
  178.     sarg++;
  179.     for ( ; ; len--) {
  180.  
  181.     /*SUPPRESS 560*/
  182.     if (len <= 0 || !(arg = *sarg++))
  183.         arg = &sv_no;
  184.  
  185.     /*SUPPRESS 530*/
  186.     for ( ; t < send && *t != '%'; t++) ;
  187.     if (t >= send)
  188.         break;        /* end of run_format string, ignore extra args */
  189.     f = t;
  190.     *buf = '\0';
  191.     xs = buf;
  192. #ifdef HAS_QUAD
  193.     doquad =
  194. #endif /* HAS_QUAD */
  195.     dolong = FALSE;
  196.     pre = post = 0;
  197.     for (t++; t < send; t++) {
  198.         switch (*t) {
  199.         default:
  200.         ch = *(++t);
  201.         *t = '\0';
  202.         (void)sprintf(xs,f);
  203.         len++, sarg--;
  204.         xlen = strlen(xs);
  205.         break;
  206.         case 'n': case '*':
  207.         croak("Use of %c in printf format not supported", *t);
  208.  
  209.         case '0': case '1': case '2': case '3': case '4':
  210.         case '5': case '6': case '7': case '8': case '9': 
  211.         case '.': case '#': case '-': case '+': case ' ':
  212.         continue;
  213.         case 'l':
  214. #ifdef HAS_QUAD
  215.         if (dolong) {
  216.             dolong = FALSE;
  217.             doquad = TRUE;
  218.         } else
  219. #endif
  220.         dolong = TRUE;
  221.         continue;
  222.         case 'c':
  223.         ch = *(++t);
  224.         *t = '\0';
  225.         xlen = SvIV(arg);
  226.         if (strEQ(f,"%c")) { /* some printfs fail on null chars */
  227.             *xs = xlen;
  228.             xs[1] = '\0';
  229.             xlen = 1;
  230.         }
  231.         else {
  232.             (void)sprintf(xs,f,xlen);
  233.             xlen = strlen(xs);
  234.         }
  235.         break;
  236.         case 'D':
  237.         dolong = TRUE;
  238.         /* FALL THROUGH */
  239.         case 'd':
  240.         ch = *(++t);
  241.         *t = '\0';
  242. #ifdef HAS_QUAD
  243.         if (doquad)
  244.             (void)sprintf(buf,s,(Quad_t)SvNV(arg));
  245.         else
  246. #endif
  247.         if (dolong)
  248.             (void)sprintf(xs,f,(long)SvNV(arg));
  249.         else
  250.             (void)sprintf(xs,f,SvIV(arg));
  251.         xlen = strlen(xs);
  252.         break;
  253.         case 'X': case 'O':
  254.         dolong = TRUE;
  255.         /* FALL THROUGH */
  256.         case 'x': case 'o': case 'u':
  257.         ch = *(++t);
  258.         *t = '\0';
  259.         value = SvNV(arg);
  260. #ifdef HAS_QUAD
  261.         if (doquad)
  262.             (void)sprintf(buf,s,(unsigned Quad_t)value);
  263.         else
  264. #endif
  265.         if (dolong)
  266.             (void)sprintf(xs,f,U_L(value));
  267.         else
  268.             (void)sprintf(xs,f,U_I(value));
  269.         xlen = strlen(xs);
  270.         break;
  271.         case 'E': case 'e': case 'f': case 'G': case 'g':
  272.         ch = *(++t);
  273.         *t = '\0';
  274.         (void)sprintf(xs,f,SvNV(arg));
  275.         xlen = strlen(xs);
  276.         break;
  277.         case 's':
  278.         ch = *(++t);
  279.         *t = '\0';
  280.         xs = SvPV(arg, arglen);
  281.         xlen = (I32)arglen;
  282.         if (strEQ(f,"%s")) {    /* some printfs fail on >128 chars */
  283.             break;        /* so handle simple cases */
  284.         }
  285.         else if (f[1] == '-') {
  286.             char *mp = strchr(f, '.');
  287.             I32 min = atoi(f+2);
  288.  
  289.             if (mp) {
  290.             I32 max = atoi(mp+1);
  291.  
  292.             if (xlen > max)
  293.                 xlen = max;
  294.             }
  295.             if (xlen < min)
  296.             post = min - xlen;
  297.             break;
  298.         }
  299.         else if (isDIGIT(f[1])) {
  300.             char *mp = strchr(f, '.');
  301.             I32 min = atoi(f+1);
  302.  
  303.             if (mp) {
  304.             I32 max = atoi(mp+1);
  305.  
  306.             if (xlen > max)
  307.                 xlen = max;
  308.             }
  309.             if (xlen < min)
  310.             pre = min - xlen;
  311.             break;
  312.         }
  313.         strcpy(tokenbuf+64,f);    /* sprintf($s,...$s...) */
  314.         *t = ch;
  315.         (void)sprintf(buf,tokenbuf+64,xs);
  316.         xs = buf;
  317.         xlen = strlen(xs);
  318.         break;
  319.         }
  320.         /* end of switch, copy results */
  321.         *t = ch;
  322.         if (xs == buf && xlen >= sizeof(buf)) {    /* Ooops! */
  323.         fputs("panic: sprintf overflow - memory corrupted!\n",stderr);
  324.         my_exit(1);
  325.         }
  326.         SvGROW(sv, SvCUR(sv) + (f - s) + xlen + 1 + pre + post);
  327.         sv_catpvn(sv, s, f - s);
  328.         if (pre) {
  329.         repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, pre);
  330.         SvCUR(sv) += pre;
  331.         }
  332.         sv_catpvn(sv, xs, xlen);
  333.         if (post) {
  334.         repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, post);
  335.         SvCUR(sv) += post;
  336.         }
  337.         s = t;
  338.         break;        /* break from for loop */
  339.     }
  340.     }
  341.     sv_catpvn(sv, s, t - s);
  342.     SvSETMAGIC(sv);
  343. }
  344.  
  345. void
  346. do_vecset(sv)
  347. SV *sv;
  348. {
  349.     SV *targ = LvTARG(sv);
  350.     register I32 offset;
  351.     register I32 size;
  352.     register unsigned char *s;
  353.     register unsigned long lval;
  354.     I32 mask;
  355.     STRLEN targlen;
  356.     STRLEN len;
  357.  
  358.     if (!targ)
  359.     return;
  360.     s = (unsigned char*)SvPV_force(targ, targlen);
  361.     lval = U_L(SvNV(sv));
  362.     offset = LvTARGOFF(sv);
  363.     size = LvTARGLEN(sv);
  364.     
  365.     len = (offset + size + 7) / 8;
  366.     if (len > targlen) {
  367.     s = (unsigned char*)SvGROW(targ, len + 1);
  368.     (void)memzero(s + targlen, len - targlen + 1);
  369.     SvCUR_set(targ, len);
  370.     }
  371.     
  372.     if (size < 8) {
  373.     mask = (1 << size) - 1;
  374.     size = offset & 7;
  375.     lval &= mask;
  376.     offset >>= 3;
  377.     s[offset] &= ~(mask << size);
  378.     s[offset] |= lval << size;
  379.     }
  380.     else {
  381.     offset >>= 3;
  382.     if (size == 8)
  383.         s[offset] = lval & 255;
  384.     else if (size == 16) {
  385.         s[offset] = (lval >> 8) & 255;
  386.         s[offset+1] = lval & 255;
  387.     }
  388.     else if (size == 32) {
  389.         s[offset] = (lval >> 24) & 255;
  390.         s[offset+1] = (lval >> 16) & 255;
  391.         s[offset+2] = (lval >> 8) & 255;
  392.         s[offset+3] = lval & 255;
  393.     }
  394.     }
  395. }
  396.  
  397. void
  398. do_chop(astr,sv)
  399. register SV *astr;
  400. register SV *sv;
  401. {
  402.     STRLEN len;
  403.     char *s;
  404.     
  405.     if (SvTYPE(sv) == SVt_PVAV) {
  406.     register I32 i;
  407.         I32 max;
  408.     AV* av = (AV*)sv;
  409.         max = AvFILL(av);
  410.         for (i = 0; i <= max; i++) {
  411.         sv = (SV*)av_fetch(av, i, FALSE);
  412.         if (sv && ((sv = *(SV**)sv), sv != &sv_undef))
  413.         do_chop(astr, sv);
  414.     }
  415.         return;
  416.     }
  417.     if (SvTYPE(sv) == SVt_PVHV) {
  418.         HV* hv = (HV*)sv;
  419.     HE* entry;
  420.         (void)hv_iterinit(hv);
  421.         /*SUPPRESS 560*/
  422.         while (entry = hv_iternext(hv))
  423.             do_chop(astr,hv_iterval(hv,entry));
  424.         return;
  425.     }
  426.     s = SvPV(sv, len);
  427.     if (len && !SvPOK(sv))
  428.     s = SvPV_force(sv, len);
  429.     if (s && len) {
  430.     s += --len;
  431.     sv_setpvn(astr, s, 1);
  432.     *s = '\0';
  433.     SvCUR_set(sv, len);
  434.     SvNIOK_off(sv);
  435.     }
  436.     else
  437.     sv_setpvn(astr, "", 0);
  438.     SvSETMAGIC(sv);
  439.  
  440. I32
  441. do_chomp(sv)
  442. register SV *sv;
  443. {
  444.     register I32 count;
  445.     STRLEN len;
  446.     char *s;
  447.  
  448.     if (RsSNARF(rs))
  449.     return 0;
  450.     count = 0;
  451.     if (SvTYPE(sv) == SVt_PVAV) {
  452.     register I32 i;
  453.         I32 max;
  454.     AV* av = (AV*)sv;
  455.         max = AvFILL(av);
  456.         for (i = 0; i <= max; i++) {
  457.         sv = (SV*)av_fetch(av, i, FALSE);
  458.         if (sv && ((sv = *(SV**)sv), sv != &sv_undef))
  459.         count += do_chomp(sv);
  460.     }
  461.         return count;
  462.     }
  463.     if (SvTYPE(sv) == SVt_PVHV) {
  464.         HV* hv = (HV*)sv;
  465.     HE* entry;
  466.         (void)hv_iterinit(hv);
  467.         /*SUPPRESS 560*/
  468.         while (entry = hv_iternext(hv))
  469.             count += do_chomp(hv_iterval(hv,entry));
  470.         return count;
  471.     }
  472.     s = SvPV(sv, len);
  473.     if (len && !SvPOKp(sv))
  474.     s = SvPV_force(sv, len);
  475.     if (s && len) {
  476.     s += --len;
  477.     if (RsPARA(rs)) {
  478.         if (*s != '\n')
  479.         goto nope;
  480.         ++count;
  481.         while (len && s[-1] == '\n') {
  482.         --len;
  483.         --s;
  484.         ++count;
  485.         }
  486.     }
  487.     else {
  488.         STRLEN rslen;
  489.         char *rsptr = SvPV(rs, rslen);
  490.         if (rslen == 1) {
  491.         if (*s != *rsptr)
  492.             goto nope;
  493.         ++count;
  494.         }
  495.         else {
  496.         if (len < rslen)
  497.             goto nope;
  498.         len -= rslen - 1;
  499.         s -= rslen - 1;
  500.         if (bcmp(s, rsptr, rslen))
  501.             goto nope;
  502.         count += rslen;
  503.         }
  504.     }
  505.     *s = '\0';
  506.     SvCUR_set(sv, len);
  507.     SvNIOK_off(sv);
  508.     }
  509.   nope:
  510.     SvSETMAGIC(sv);
  511.     return count;
  512.  
  513. void
  514. do_vop(optype,sv,left,right)
  515. I32 optype;
  516. SV *sv;
  517. SV *left;
  518. SV *right;
  519. {
  520. #ifdef LIBERAL
  521.     register long *dl;
  522.     register long *ll;
  523.     register long *rl;
  524. #endif
  525.     register char *dc;
  526.     STRLEN leftlen;
  527.     STRLEN rightlen;
  528.     register char *lc = SvPV(left, leftlen);
  529.     register char *rc = SvPV(right, rightlen);
  530.     register I32 len;
  531.     I32 lensave;
  532.  
  533.     dc = SvPV_force(sv,na);
  534.     len = leftlen < rightlen ? leftlen : rightlen;
  535.     lensave = len;
  536.     if (SvCUR(sv) < len) {
  537.     dc = SvGROW(sv,len + 1);
  538.     (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1);
  539.     }
  540.     SvCUR_set(sv, len);
  541.     (void)SvPOK_only(sv);
  542. #ifdef LIBERAL
  543.     if (len >= sizeof(long)*4 &&
  544.     !((long)dc % sizeof(long)) &&
  545.     !((long)lc % sizeof(long)) &&
  546.     !((long)rc % sizeof(long)))    /* It's almost always aligned... */
  547.     {
  548.     I32 remainder = len % (sizeof(long)*4);
  549.     len /= (sizeof(long)*4);
  550.  
  551.     dl = (long*)dc;
  552.     ll = (long*)lc;
  553.     rl = (long*)rc;
  554.  
  555.     switch (optype) {
  556.     case OP_BIT_AND:
  557.         while (len--) {
  558.         *dl++ = *ll++ & *rl++;
  559.         *dl++ = *ll++ & *rl++;
  560.         *dl++ = *ll++ & *rl++;
  561.         *dl++ = *ll++ & *rl++;
  562.         }
  563.         break;
  564.     case OP_BIT_XOR:
  565.         while (len--) {
  566.         *dl++ = *ll++ ^ *rl++;
  567.         *dl++ = *ll++ ^ *rl++;
  568.         *dl++ = *ll++ ^ *rl++;
  569.         *dl++ = *ll++ ^ *rl++;
  570.         }
  571.         break;
  572.     case OP_BIT_OR:
  573.         while (len--) {
  574.         *dl++ = *ll++ | *rl++;
  575.         *dl++ = *ll++ | *rl++;
  576.         *dl++ = *ll++ | *rl++;
  577.         *dl++ = *ll++ | *rl++;
  578.         }
  579.     }
  580.  
  581.     dc = (char*)dl;
  582.     lc = (char*)ll;
  583.     rc = (char*)rl;
  584.  
  585.     len = remainder;
  586.     }
  587. #endif
  588.     {
  589.     char *lsave = lc;
  590.     char *rsave = rc;
  591.     
  592.     switch (optype) {
  593.     case OP_BIT_AND:
  594.         while (len--)
  595.         *dc++ = *lc++ & *rc++;
  596.         break;
  597.     case OP_BIT_XOR:
  598.         while (len--)
  599.         *dc++ = *lc++ ^ *rc++;
  600.         goto mop_up;
  601.     case OP_BIT_OR:
  602.         while (len--)
  603.         *dc++ = *lc++ | *rc++;
  604.       mop_up:
  605.         len = lensave;
  606.         if (rightlen > len)
  607.         sv_catpvn(sv, rsave + len, rightlen - len);
  608.         else if (leftlen > len)
  609.         sv_catpvn(sv, lsave + len, leftlen - len);
  610.         else
  611.         *SvEND(sv) = '\0';
  612.         break;
  613.     }
  614.     }
  615. }
  616.  
  617. OP *
  618. do_kv(ARGS)
  619. dARGS
  620. {
  621.     dSP;
  622.     HV *hv = (HV*)POPs;
  623.     I32 i;
  624.     register HE *entry;
  625.     char *tmps;
  626.     SV *tmpstr;
  627.     I32 dokeys =   (op->op_type == OP_KEYS);
  628.     I32 dovalues = (op->op_type == OP_VALUES);
  629.  
  630.     if (op->op_type == OP_RV2HV || op->op_type == OP_PADHV) 
  631.     dokeys = dovalues = TRUE;
  632.  
  633.     if (!hv)
  634.     RETURN;
  635.  
  636.     (void)hv_iterinit(hv);    /* always reset iterator regardless */
  637.  
  638.     if (GIMME != G_ARRAY) {
  639.     dTARGET;
  640.  
  641.     if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
  642.         i = HvKEYS(hv);
  643.     else {
  644.         i = 0;
  645.         /*SUPPRESS 560*/
  646.         while (entry = hv_iternext(hv)) {
  647.         i++;
  648.         }
  649.     }
  650.     PUSHi( i );
  651.     RETURN;
  652.     }
  653.  
  654.     /* Guess how much room we need.  hv_max may be a few too many.  Oh well. */
  655.     EXTEND(sp, HvMAX(hv) * (dokeys + dovalues));
  656.  
  657.     PUTBACK;    /* hv_iternext and hv_iterval might clobber stack_sp */
  658.     while (entry = hv_iternext(hv)) {
  659.     SPAGAIN;
  660.     if (dokeys) {
  661.         tmps = hv_iterkey(entry,&i);    /* won't clobber stack_sp */
  662.         if (!i)
  663.         tmps = "";
  664.         XPUSHs(sv_2mortal(newSVpv(tmps,i)));
  665.     }
  666.     if (dovalues) {
  667.         tmpstr = NEWSV(45,0);
  668.         PUTBACK;
  669.         sv_setsv(tmpstr,hv_iterval(hv,entry));
  670.         SPAGAIN;
  671.         DEBUG_H( {
  672.         sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
  673.             HvMAX(hv)+1,entry->hent_hash & HvMAX(hv));
  674.         sv_setpv(tmpstr,buf);
  675.         } )
  676.         XPUSHs(sv_2mortal(tmpstr));
  677.     }
  678.     PUTBACK;
  679.     }
  680.     return NORMAL;
  681. }
  682.  
  683.